import Head from 'next/head';
import TableOptionsTable from '../../../components/prop-tables/TableOptionsTable';
import ColumnOptionsTable from '../../../components/prop-tables/ColumnOptionsTable';
import StateOptionsTable from '../../../components/prop-tables/StateOptionsTable';
import MultiSortingExample from '../../../examples/multi-sorting';
import RemoteExample from '../../../examples/remote';

<Head>
  <title>Sorting Feature Guide - Mantine React Table Docs</title>
  <meta
    name="description"
    content="How to use, customize, or disable sorting features in Mantine React Table"
  />
</Head>

## Sorting Feature Guide

Mantine React Table supports almost any sorting scenario you may have. Client-side sorting is enabled by default, but you can opt to implement your own server-side sorting logic, or even replace the default client-side sorting with your own implementation.

### Relevant Table Options

<TableOptionsTable
  onlyOptions={
    new Set([
      'enableGlobalFilterRankedResults',
      'enableMultiSort',
      'enableSorting',
      'enableSortingRemoval',
      'getSortedRowModel',
      'isMultiSortEvent',
      'manualSorting',
      'maxMultiSortColCount',
      'onSortingChange',
      'sortDescFirst',
      'sortingFns',
    ])
  }
/>

### Relevant Column Options

<ColumnOptionsTable
  onlyOptions={
    new Set([
      'enableMultiSort',
      'enableSorting',
      'invertSorting',
      'sortDescFirst',
      'sortUndefined',
      'sortingFn',
    ])
  }
/>

### Relevant State Options

<StateOptionsTable onlyOptions={new Set(['sorting'])} />

### Disable Sorting

Sorting can be disabled globally by setting the `enableSorting` table option to `false`. This will disable sorting for all columns. You can also disable sorting for individual columns by setting the `enableSorting` column option to `false`.

```jsx
const columns = [
  {
    accessorKey: 'name',
    header: 'Name',
    enableSorting: false, // disable sorting for this column
  },
];

const table = useMantineReactTable({
  columns,
  data,
  enableSorting: false, //disable sorting for all columns
});

return <MantineReactTable table={table} />;
```

### Initial/Default Sorting

You can sort by a column or multiple columns by default by setting the `sorting` state option in either the `initialState` or `state` table options.

```jsx
const table = useMantineReactTable({
  columns,
  data,
  initialState: {
    sorting: [
      {
        id: 'age', //sort by age by default on page load
        desc: true,
      },
      {
        id: 'lastName', //then sort by lastName if age is the same
        desc: true,
      },
    ],
  },
});
```

### Default Sorting Features

Client-side sorting is enabled by default. When sorting is toggled on for a column, the table will be sorted by an [`alphanumeric` sorting algorithm](https://tanstack.com/table/v8/docs/api/features/sorting#sorting-functions) by default.

#### Multi-Sorting

Multi-sorting is also enabled by default, which means a user can sort by multiple columns at once. This can be accomplished by clicking on a column header while holding down the `shift` key. The table will then be sorted by the previously sorted column, and then by the newly clicked column. Or if you want multi-sorting to be the default click behavior without the need to hold `shift`, you can set the `isMultiSortEvent` table option to `() => true`.

```jsx
const table = useMantineReactTable({
  columns,
  data,
  isMultiSortEvent: () => true, //multi-sorting will be the default click behavior without the need to hold shift
});
```

You can limit the number of columns that can be sorted at once by setting the `maxMultiSortColCount` table option, or you can disable multi-sorting entirely by setting the `enableMultiSort` table option to `false`.

#### Sorting Removal

By default, users can remove a sort on a column by clicking through the sort direction options or selecting "Clear Sort" from the column actions menu. You can disable this feature by setting the `enableSortingRemoval` table option to `false`.

```jsx
const table = useMantineReactTable({
  columns,
  data,
  enableSortingRemoval: false, //users will not be able to remove a sort on a column
});
```

#### Sort Direction

By default, columns with `string` datatypes will sort alphabetically in ascending order, but columns with `number` datatypes will sort numerically in descending order. You can change the default sort direction per column by specifying the `sortDescFirst` column option to either `true` or `false`. You can also change the default sort direction globally by setting the `sortDescFirst` table option to either `true` or `false`.

<MultiSortingExample />

### Sorting Functions

By default, Mantine React Table will use an `alphanumeric` sorting function for all columns.

There are 6 built-in sorting functions that you can choose from: ` alphanumeric`, `alphanumericCaseSensitive`, `text`, `textCaseSensitive`, `datetime`, and `basic`. You can learn more about these built-in sorting function in the [TanStack Table Sorting API docs](https://tanstack.com/table/v8/docs/api/features/sorting#sorting-functions).

#### Add Custom Sorting Functions

If none of these sorting functions meet your needs, you can add your own custom sorting functions by specifying more sorting functions in the `sortingFns` table option.

```jsx
const table = useMantineReactTable({
  columns,
  data,
  sortingFns: {
    //will add a new sorting function to the list of other sorting functions already available
    myCustomSortingFn: (rowA, rowB, columnId) => // your custom sorting logic
  },
});
```

#### Change Sorting Function Per Column

You can now choose a sorting function for each column by either passing a string value of the built-in sorting function names to the `sortingFn` column option, or by passing a custom sorting function to the `sortingFn` column option.

```tsx
const columns = [
  {
    accessorKey: 'name',
    header: 'Name',
    sortingFn: 'textCaseSensitive', //use the built-in textCaseSensitive sorting function instead of the default alphanumeric sorting function
  },
  {
    accessorKey: 'age',
    header: 'Age',
    //use your own custom sorting function instead of any of the built-in sorting functions
    sortingFn: (rowA, rowB, columnId) => // your custom sorting logic
  },
];
```

### Manual Server-Side Sorting

If you are working with large data sets, you may want to let your back-end apis handle all of the sorting and pagination processing instead of doing it client-side. You can do this by setting the `manualSorting` table option to `true`. This will disable the default client-side sorting and pagination features, and will allow you to implement your own sorting and pagination logic.

> When `manualSorting` is set to `true`, Mantine React Table assumes that your `data` is already sorted by the time you are passing it to the table.

If you need to sort your data in a back-end api, then you will also probably need access to the internal `sorting` state from the table. You can do this by managing the `sorting` state yourself, and then passing it to the table via the `state` table option. You can also pass a callback function to the `onSortingChange` table option, which will be called whenever the `sorting` state changes internally in the table

```tsx
const [sorting, setSorting] = useState([]);

useEffect(() => {
  //do something with the sorting state when it changes
}, [sorting]);

const table = useMantineReactTable({
  columns,
  data,
  manualSorting: true,
  state: { sorting },
  onSortingChange: setSorting,
});

return <MantineReactTable table={table} />;
```

#### Remote Sorting Example

Here is the full Remote Data example showing how to implement server-side sorting, filtering, and pagination with Mantine React Table.

<RemoteExample />

View Extra Storybook **[Examples](https://www.mantine-react-table.dev/?path=/story/features-sorting-examples)**
